import { app, BrowserWindow, desktopCapturer, screen, webContents, shell, clipboard } from 'electron'
import https from 'https';
import * as fs from 'fs';
import * as path from 'path';
import { exec } from 'child_process';

export function isProcessRunningWin(name) {
  return new Promise(resolve => {
    exec('tasklist', (err, stdout) => {
      if (err) return resolve(false);
      resolve(stdout.toLowerCase().includes(name.toLowerCase()));
    });
  });
}

// 检测安装包是否存在
export function monitorAppFiles() {
  const appPath = app.getAppPath(); // 获取打包后资源路径
  const criticalFiles = [
    path.join(appPath, 'package.json'), // 或其他关键资源
    path.join(path.dirname(appPath), 'resources', 'app.asar') // 如果有 asar
  ];

  setInterval(() => {
    for (const file of criticalFiles) {
      if (!fs.existsSync(file)) {
        console.error(`关键文件丢失: ${file}, 即将退出应用...`);
        app.quit();
        return;
      }
    }
  }, 3000); // 每3秒检测一次
}

// 检查是否内网
export function checkInternal(url: string): Promise<boolean> {
  return new Promise((resolve) => {
    const options = {
      hostname: url,
      port: 443,
      path: '/',
      method: 'GET',
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
      },
    };
    const req = https.request(options, (res) => {
      let data = '';
      res.on('data', chunk => data += chunk.toString());
      res.on('end', () => {
        // 根据页面内容判断
        if (data.includes('访问失败') || data.includes('访问失败，请尝试以下方法后再次访问')) {
          resolve(false); // 外网
        } else {
          resolve(true); // 内网
        }
      });
    });

    req.on('error', () => resolve(false));
    req.setTimeout(5000, () => {
      req.destroy();
      resolve(false);
    });

    req.end();
  });
}

// 获取屏幕分辨率
export function getSize() {
  const { size, scaleFactor, workAreaSize } = screen.getPrimaryDisplay()
  console.log(size, scaleFactor, workAreaSize)
  return {
    width: size.width,
    height: size.height,
    scaleFactor,
  }
}

// 获取当前打开的窗口
const selfWindows = async () =>
  await Promise.all(
    webContents
      .getAllWebContents()
      .filter((item) => {
        const win = BrowserWindow.fromWebContents(item)
        return win && win.isVisible()
      })
      .map(async (item) => {
        const win = BrowserWindow.fromWebContents(item)
        const thumbnail = await win?.capturePage()
        // 当程序窗口打开DevTool的时候  也会计入
        return {
          name: win?.getTitle() + (item.devToolsWebContents === null ? '' : '-dev'), // 给dev窗口加上后缀
          id: win?.getMediaSourceId(),
          thumbnail,
          display_id: '',
          appIcon: null
        }
      })
  )

// 获取屏幕或窗口列表
export const getDesktopCapturerSource = async (type: 'screen' | 'window' = 'window') => {
  return [
    ...(await desktopCapturer.getSources({ types: ['screen'] })),
    ...(type === 'screen' ? [] : await selfWindows())
  ]
}

// 获取屏幕级别
export const getScreenLevel = (): '1K' | '2K' | '4K' | 'Other' => {
  const primaryDisplay = screen.getPrimaryDisplay();
  const { width, height } = primaryDisplay.size;

  if (width >= 3840 || height >= 2160) {
    return '4K';
  } else if (width >= 2560 || height >= 1440) {
    return '2K';
  } else if (width >= 1920 || height >= 1080) {
    return '1K';
  }
  return 'Other';
}

/**
 * 发送命令到目标应用
 * protocol : 'myapp'  // 目标应用的协议
 * command: 'open'  // 目标应用要执行的命令
 * params: { type: 'settings', id: '123' }  // 目标应用要执行的命令的参数
 * new URLSearchParams(params).toString() === type=settings&id=123
 */

export const sendCommandToTarget = (protocol, command, params = {}) => {
  // 构建协议URL
  const url = `${protocol}://${command}?${new URLSearchParams(params).toString()}`;
  console.log(`Sending command: ${url}`);
  // 使用shell打开协议URL，这会触发目标应用
  shell.openExternal(url);
}

/**
 * 打开文件夹（目录）
 * @param url 路径（绝对路径）
 * @returns Promise<void>
 */
export const openFolder = async (url: string) => {
  try {
    if (!fs.existsSync(url)) {
      console.error('openFolder error: 路径不存在', url)
      return
    }

    const stats = fs.statSync(url)
    let targetPath = url

    if (stats.isFile()) {
      // 如果传的是文件，取父目录
      targetPath = require('path').dirname(url)
    }

    const result = await shell.openPath(targetPath)
    if (result) {
      console.error('打开文件夹失败:', result)
    }
  } catch (err) {
    console.error('openFolder error:', err)
  }
}

/**
 * 打开文件（并选中）
 * @param url 路径（绝对路径，文件路径）
 */
export const openFile = (url: string) => {
  try {
    if (!fs.existsSync(url)) {
      console.error('openFile error: 路径不存在', url)
      return
    }
    const stats = fs.statSync(url)

    if (stats.isDirectory()) {
      // 如果传的是目录，直接打开目录
      shell.openPath(url)
    } else {
      shell.openPath(url).then((errMsg) => {
        if (errMsg) {
          console.error('打开文件失败:', errMsg)
        } else {
          console.log('文件已打开:', url)
        }
      })
    }
  } catch (err) {
    console.error('openFile error:', err)
  }
}

/**
 * 复制文件到剪切板
 * （效果等同于资源管理器里右键 → 复制文件，可以在微信等应用中 Ctrl+V 粘贴）
 * @param filePath 文件路径（绝对路径）
 * @returns Promise<boolean> 返回操作是否成功
 */
export const copyFileToClipboard = async (filePath: string): Promise<boolean> => {
  try {
    // 规范化路径
    const normalizedPath = path.resolve(filePath)
    
    // 检查文件是否存在
    if (!fs.existsSync(normalizedPath)) {
      console.error('copyFileToClipboard error: 文件不存在', normalizedPath)
      return false
    }

    // 检查是否为文件
    const stats = fs.statSync(normalizedPath)
    if (!stats.isFile()) {
      console.error('copyFileToClipboard error: 路径不是文件', normalizedPath)
      return false
    }

    // 检查文件大小（避免复制过大文件）
    const maxSize = 500 * 1024 * 1024 // 500MB
    if (stats.size > maxSize) {
      console.error('copyFileToClipboard error: 文件过大', `${stats.size} bytes`)
      return false
    }

    // 清空剪切板
    clipboard.clear()
    
    // 尝试多种方法确保微信等应用的兼容性
    try {
      // 方法1: 使用 PowerShell 脚本复制文件对象（最兼容微信）
      const powershellScript = `
        Add-Type -AssemblyName System.Windows.Forms
        $file = Get-Item "${normalizedPath.replace(/\\/g, '\\\\')}"
        $dataObject = New-Object System.Windows.Forms.DataObject
        $fileCollection = New-Object System.Collections.Specialized.StringCollection
        $fileCollection.Add($file.FullName)
        $dataObject.SetFileDropList($fileCollection)
        [System.Windows.Forms.Clipboard]::SetDataObject($dataObject, $true)
      `
      
      return new Promise<boolean>((resolve) => {
        exec(powershellScript, { 
          shell: 'powershell.exe',
          windowsHide: true,
          timeout: 30000
        }, async (error, _stdout, _stderr) => {
          if (error) {
            console.warn('PowerShell 方法失败，尝试传统方法:', error.message)
            // 如果 PowerShell 失败，尝试传统方法
            const fallbackResult = await tryTraditionalMethods(normalizedPath)
            resolve(fallbackResult)
          } else {
            console.log('使用 PowerShell 成功复制文件到剪切板:', normalizedPath)
            resolve(true)
          }
        })
      })
      
    } catch (err) {
      console.warn('PowerShell 方法异常，使用传统方法:', err)
      return await tryTraditionalMethods(normalizedPath)
    }
  } catch (err) {
    console.error('copyFileToClipboard error:', err)
    return false
  }
}

/**
 * 传统剪切板方法（备用方案）
 * @param normalizedPath 规范化的文件路径
 * @returns Promise<boolean>
 */
const tryTraditionalMethods = async (normalizedPath: string): Promise<boolean> => {
  try {
    // 方法2: CF_HDROP 格式（Windows 文件拖放格式）
    const pathBuffer = Buffer.from(normalizedPath + '\0', 'utf16le')
    const headerSize = 20
    const totalSize = headerSize + pathBuffer.length + 2 // +2 for double null terminator
    
    const dropFilesBuffer = Buffer.alloc(totalSize)
    
    // DROPFILES 结构头部
    dropFilesBuffer.writeUInt32LE(headerSize, 0)  // pFiles offset
    dropFilesBuffer.writeUInt32LE(0, 4)           // pt.x
    dropFilesBuffer.writeUInt32LE(0, 8)           // pt.y
    dropFilesBuffer.writeUInt32LE(0, 12)          // fNC
    dropFilesBuffer.writeUInt32LE(1, 16)          // fWide (Unicode)
    
    // 复制文件路径
    pathBuffer.copy(dropFilesBuffer, headerSize)
    
    // 双重 null 终止符
    dropFilesBuffer.writeUInt16LE(0, totalSize - 2)
    
    clipboard.writeBuffer('CF_HDROP', dropFilesBuffer)
    console.log('使用 CF_HDROP 格式复制文件到剪切板:', normalizedPath)
    return true
    
  } catch (err) {
    console.warn('CF_HDROP 方法失败，尝试 FileNameW:', err)
    
    try {
      // 方法3: FileNameW 格式
      const fileNameBuffer = Buffer.from(normalizedPath + '\0', 'utf16le')
      clipboard.writeBuffer('FileNameW', fileNameBuffer)
      console.log('使用 FileNameW 格式复制文件到剪切板:', normalizedPath)
      return true
      
    } catch (err2) {
      console.warn('FileNameW 方法失败，尝试文本格式:', err2)
      
      try {
        // 方法4: 纯文本格式（最后备用）
        clipboard.writeText(normalizedPath)
        console.log('使用文本格式复制文件路径到剪切板:', normalizedPath)
        return true
        
      } catch (err3) {
        console.error('所有复制方法都失败了:', err3)
        return false
      }
    }
  }
}

